
dofile "clickable_common.lua"       --remove in real script
dofile "command_defs.lua"           --remove in real script
dofile "devices.lua"                --remove in real script
dofile "clickabledata.lua"          --remove in real script


g_sendPort  = 30334;
g_recvPort  = 30335;
g_Host      = "127.0.0.1" 

Device = {}
Device.__index = Device;

function Device.create()
	local dev = {}
	setmetatable(dev, Device);
	return dev;
end

function Device.get_argument_value(argNumber)
	return 0;
    --return math.random();
end

function Device.performClickableAction(id, value)
    print("click action performed");
end

function GetDevice(deviceId)
	return Device.create();
end

pnames  = {}
props   = {}
ptd     = {}
ptc     = {}

g_OldValues = {}


function ValueHasChanged(index, newValue)
	return g_OldValues[index] ~= newValue; -- convert to epsilon convert later 
end

function Log(message)
  print(message);
  if default_output_file then
    default_output_file:write(message .. "\n");
  end
end

function LuaExportStart()
  default_output_file = io.open("./Temp/Export.log", "w")
  Log("LuaExportStart");
  package.path = package.path.."C:\\Software\\Games\\Steam\\steamapps\\common\dcs a-10c warthog\\LuaSocket\\?.lua"
  package.cpath = package.cpath.."C:\\Software\\Games\\Steam\\steamapps\\common\dcs a-10c warthog\\LuaSocket\\bin\\?.dll"
  --package.path  = package.path..";.\\LuaSocket\\?.lua"
  --package.cpath = package.cpath..";.\\LuaSocket\\?.dll"
  socket = require("socket")

  InitPropertyNamesTable();
  InitAdditionalTables();

  c = socket.udp();
  socket.try(c:setsockname(g_Host, g_recvPort));
  socket.try(c:settimeout(0.001));

  for i, propId in ipairs(props) do
	g_OldValues[propId] = 0.0;
  end
  --send a handshake to the server
  Log("Sending Handshake");
  socket.try(c:sendto("<hs>DcsA10;DCS A10</hs>", g_Host, g_sendPort))
end

function LuaExportBeforeNextFrame()
	Log("exportbefore");
	g_Received = c:receive();
	if g_Received then
	    Log("received: " .. g_Received);   
        if ProcessCommands(g_Received) == false then 
            Log("Received invalid packet, buffer will be cleared -> maybe some commands got lost");
        end
	end
end

function ProcessCommands(input)

    local s1, e1 = string.find(input, "<cmds>");
    local s2, e2 = string.find(input, "</cmds>");

    if s1 == nil or e1 == nil or s2 == nil or e2 == nil then
        return false;
    end

    local cmdString     = string.sub(input, e1 + 1, s2 - 1);
    local cmds          = Split(cmdString, ';')

    for index, content in pairs(cmds) do
        print("content: " .. content);
        local tuple     = Split(content, '=');
        local id        = tuple[1];
        local value     = tuple[2];
        print("id: " .. id);
        print("value: " .. value);

        ExecuteSetValue(id, value);

    end


    return true;
end

function ExecuteSetValue(argNumber, value)
    
    -- Enable for Debug purposes
    --Log("ptc: ");
    --for k,v in pairs(ptc) do print(k, v) end
        
    Log("executing set value with argnumber " .. argNumber .. " and value " .. value);
    local num           = argNumber + 0; -- convert string to int (oh my fu**** lua)
    local deviceId      = ptd[num];
    local commandId     = ptc[num];

    local device = GetDevice(deviceId)
	if type(device) == "table" then
        Log("performing clickable Action on Device " .. deviceId .. " and command " .. commandId);
	    device:performClickableAction(commandId, value);	
	end    
end

function LuaExportActivityNextEvent(t)
	local tNext = t

	Log("LuaExportNextEvent");

	local dataToSend = "";
	
    local lastDev = nil;
    local device    = nil;

	for i, p in pairs(props) do
        local devId     = ptd[p];
        if devId ~= lastDev or device == nil then
            device      = GetDevice(devId);
        end
		local value     = device:get_argument_value(p);
		--print(string.format("%f", value));
		if ValueHasChanged(i, value) then
			g_OldValues[p] = value;
			dataToSend = dataToSend .. string.format("%i=%.2f;", p, value);
		end
	end
  
	--print("Sending: " .. dataToSend);
	socket.try(c:sendto(string.format("<data>%s</data>", dataToSend), g_Host, g_sendPort));	
	tNext = tNext + 0.5

	return tNext
end

function first(tbl)
    for k,v in pairs(tbl) do
        return v;
    end
end

function InitPropertyNamesTable()
    pnames = 
    {
        "PTR-EPP-APU-GEN-PWR",
    };
end

function InitAdditionalTables()

    -- replace for this for to only take the subset of properties registered in pnames table
    --for k,v in pairs(pnames) do
    --     local ele           = elements[v];

    for k,v in pairs(elements) do
        local ele           = v;

        --+0 for int casting (lua stuff :( )
        local propertyId    = first(ele.arg);
        local commandId     = first(ele.action);
        local deviceId      = ele.device; 

        ptd[propertyId + 0]      = deviceId;
        
        if commandId ~= nil then
            ptc[propertyId + 0]  = commandId;
        end

        --Log("cmdId: " .. tostring(commandId));
        --Log("deviceId: " .. tostring(deviceId));
        --Log("PropertyId: " .. tostring(propertyId));

        -- Enable for Debug purposes
        --print("ptd: ");
        --for k,v in pairs(ptd) do print(k, v) end

        -- Enable for Debug purposes
        --print("ptc: ");
        --for k,v in pairs(ptc) do print(k, v) end
    end
end

-- Compatibility: Lua-5.0
function Split(str, delim, maxNb)
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    if maxNb == nil or maxNb < 1 then
        maxNb = 0    -- No limit
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gfind(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
        if nb == maxNb then break end
    end
    -- Handle the last field
    if nb ~= maxNb then
        result[nb + 1] = string.sub(str, lastPos)
    end
    return result
end